home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1995 October
/
EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso
/
Aminet
/
misc
/
emu
/
prlink_amiga.lha
/
prlink-0.8.0a
/
src
/
pramiga.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-04-25
|
9KB
|
361 lines
#include "prtrans.h"
/*
* Note that for the Amiga only the pramiga cable is supported. This is
* because nobody would/could use the pc64 or 64net cables, because they
* are for compatibility with pc software. To make up for this, we can use
* the same prlink cable to its full potential by using all 8 data lines
* bidirectionally.
*
* To enable this, define PRLINK88 (in the Makefile below), and don't forget
* to set the cable type to prlink88 in the pet/vic/64 side programs as
* well.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <exec/exec.h>
#include <resources/misc.h>
#include <hardware/cia.h>
#include <clib/exec_protos.h>
#include <clib/misc_protos.h>
/*
* The CIAs are volatile, otherwise the while loop waiting for ACK to
* change is "optimized".
*/
extern volatile struct CIA ciaa;
extern volatile struct CIA ciab;
struct Library *MiscBase;
static unsigned long MiscAllocated;
static unsigned char ack;
int bounce;
char myname[] = "pramiga.c";
#define BUSY (1 << CIAB_PRTRBUSY) /* == 0x01 */
#define POUT (1 << CIAB_PRTRPOUT) /* == 0x02 */
#define NO_ASM 1
int
prinit(void)
{
atexit(prclose);
MiscBase = OpenResource("misc.resource");
if (MiscBase == NULL) {
printf("Can't open misc.resource\n");
return -1;
} {
const char *user;
user = AllocMiscResource(MR_PARALLELPORT, myname);
if (user != NULL && user != myname) {
printf("Printer data lines already in use by %s.\n", user);
return -2;
}
MiscAllocated = 1 << MR_PARALLELPORT;
#ifndef TRANSNIB
user = AllocMiscResource(MR_PARALLELBITS, myname);
if (user != NULL && user != myname) {
printf("Printer control lines already in use by %s.\n", user);
return -3;
}
MiscAllocated |= 1 << MR_PARALLELBITS;
#endif
}
#ifndef TRANSNIB
/* turn POUT into output (BUSY is input) */
ciab.ciaddra = (ciab.ciaddra | POUT) & ~BUSY;
ciab.ciapra |= POUT; /* and set it high */
ack = ciab.ciapra & BUSY; /* get the current state of the BUSY line */
#endif
ciaa.ciaddrb = 0xFF; /* set all lines to output */
ciaa.ciaprb = 0xFF; /* and high */
return 0;
}
void
prclose(void)
{
if (bounce != 0) {
printf("*** bounce, bounce! (%d times)\n", bounce);
bounce = 0;
}
#ifndef TRANSNIB
if (MiscAllocated & (1 << MR_PARALLELBITS)) {
ciab.ciaddra &= ~POUT; /* turn POUT back into input */
FreeMiscResource(MR_PARALLELBITS);
}
#endif
if (MiscAllocated & (1 << MR_PARALLELPORT)) {
ciaa.ciaprb = 0xFF;
ciaa.ciaddrb = 0xFF; /* set all data lines to output */
FreeMiscResource(MR_PARALLELPORT);
}
MiscAllocated = 0;
/* There is no CloseResource() function, really! */
}
void
output(unsigned char byte)
{
send(&byte, 1);
}
unsigned
input(void)
{
unsigned char byte;
receive(&byte, 1);
return byte;
}
unsigned
wait_input(void)
{
#ifdef TRANSNIB
while (ciaa.ciaprb & 0x40) /* wait for DRDY to go low */
usleep (SLEEP_TIME);
ciaa.ciaddrb = 0x80; /* set the bidirectional signals to input */
#else
ciab.ciapra &= ~POUT; /* drop the -FLAG to low */
while (ack == (BUSY & ciab.ciapra)) /* wait for BUSY to change */
usleep (SLEEP_TIME);
ciaa.ciaddrb = 0x00; /* set the bidirectional signals to input */
#endif
return input();
}
#ifndef TRANSNIB
void
send(unsigned char *buffer, unsigned length)
{
ciaa.ciaddrb = 0xFF; /* set all lines to output */
#if defined(__GNUC__) && !NO_ASM
/* INDENT OFF */
asm("
subql #1,%1
moveq #-1,d0
cmpl %1,d0
jeq .send
.sbyteloop:
moveb %2@+,%4@
andb %6,%5@
.sackloop:
moveb %5@,d0
andb %7,d0
cmpb %3,d0
jeq .sackloop
orb %8,%5@
eorb %7,%3
dbra %1,.sbyteloop
clrw %1
subql #1,%1
jcc .sbyteloop
.send:
" : "=d" (ack) /* 0 output */
: "d" (length), /* 1 input */
"a" (buffer), /* 2 */
"0" (ack), /* 3 */
"a" (&ciaa.ciaprb), /* 4 */
"a" (&ciab.ciapra), /* 5 */
"g" (~POUT), /* 6 */
"g" (BUSY), /* 7 */
"g" (POUT) /* 8 */
: "d0" /* clobbered */
);
/* INDENT ON */
#else
while (length--) {
ciaa.ciaprb = *buffer++;
ciab.ciapra &= ~POUT; /* drop the -FLAG to low */
while (ack == (BUSY & ciab.ciapra)); /* wait for BUSY to change */
ciab.ciapra |= POUT; /* raise -FLAG again */
ack ^= BUSY; /* store the new state of -BUSY */
}
#endif
}
#ifdef PRLINK88
void
receive(unsigned char *buffer, unsigned length)
{
ciaa.ciaddrb = 0x00; /* set the bidirectional signals to input */
#if defined(__GNUC__) && !NO_ASM
/* INDENT OFF */
asm("
subql #1,%1
moveq #-1,d0
cmpl %1,d0
jeq .rend
.rbyteloop:
andb %6,%5@
.rackloop:
moveb %5@,d0
andb %7,d0
cmpb %3,d0
jeq .rackloop
orb %8,%5@
moveb %4@,%2@+
eorb %7,%3
dbra %1,.rbyteloop
clrw %1
subql #1,%1
jcc .rbyteloop
.rend:
" : "=d" (ack) /* 0 output */
: "d" (length), /* 1 input */
"a" (buffer), /* 2 */
"0" (ack), /* 3 */
"a" (&ciaa.ciaprb), /* 4 data */
"a" (&ciab.ciapra), /* 5 ctl */
"g" (~POUT), /* 6 */
"g" (BUSY), /* 7 */
"g" (POUT) /* 8 */
: "d0" /* clobbered */
);
/* INDENT ON */
#else
while (length--) {
ciab.ciapra &= ~POUT; /* drop the -FLAG to low */
bounced:
while (ack == (BUSY & ciab.ciapra)); /* wait for BUSY to change */
*buffer++ = ciaa.ciaprb;/* read the byte */
ciab.ciapra |= POUT; /* raise -FLAG again */
/* debounce */
{
int bouncecount;
for (bouncecount = 0; bouncecount < 2; bouncecount++) {
if (ack == (BUSY & ciab.ciapra) || buffer[-1] != ciaa.ciaprb) {
buffer--;
bounce++;
goto bounced;
}
}
}
ack ^= BUSY; /* store the new state of -BUSY */
}
#endif
}
#else /* not PRLINK88 */
void
receive(unsigned char *buffer, unsigned length)
{
register unsigned char data;
ciaa.ciaddrb = 0x00; /* set all signals to input */
while (length--) {
ciab.ciapra &= ~POUT; /* drop the -FLAG to low */
while (ack == (BUSY & ciab.ciapra)); /* wait for BUSY to change */
ciab.ciapra |= POUT; /* raise -FLAG again */
data = ciaa.ciaprb & 0x0f; /* read the low nybble */
ciab.ciapra &= ~POUT; /* drop the -FLAG to low */
while (ack != (BUSY & ciab.ciapra)); /* wait for BUSY to change */
ciab.ciapra |= POUT; /* raise -FLAG again */
data |= (ciaa.ciaprb & 0x0f) << 4; /* read the high nybble */
*buffer++ = data;
}
}
#endif /* PRLINK88 */
#else /* TRANSNIB */
/*-
* TransNib is a cable that has only 6 bits connected:
*
* 0-3: data i/o
* 6: handshake in
* 7: handshake out
*
* Because the cable is straight-through, bits 6 and 7 are swapped
* at the PET/C-64/VIC-20 side.
*
* The protocol is provided for people who made a cable for
* TransNib V1.00 Devised by Matt Francis (m.p.francis@newcastle.ac.uk).
* Because the cable is a subset of the prlink cable it will also work
* with that.
*
* Note that this protocol is not compatible with the TransNib programs!
-*/
void
send(unsigned char *buffer, unsigned length)
{
register unsigned char data;
/*
* $40 is DRCV (input), $80 is DRDY (output) Note that the names are
* swapped from receiving but the data direction isn't!
*/
ciaa.ciaddrb = 0x8f; /* set the bidirectional signals to output */
while (length--) {
register unsigned char nibble;
data = *buffer++;
nibble = data >> 4;
ciaa.ciaprb = nibble; /* set DRDY low */
while (ciaa.ciaprb & 0x40); /* wait for DRCV to go low */
ciaa.ciaprb = nibble | 0x80; /* set DRDY high */
while (!(ciaa.ciaprb & 0x40)); /* wait for DRCV to go high */
nibble = data & 0x0F;
ciaa.ciaprb = nibble; /* set DRDY low */
while (ciaa.ciaprb & 0x40); /* wait for DRCV to go low */
ciaa.ciaprb = nibble | 0x80; /* set DRDY high */
while (!(ciaa.ciaprb & 0x40)); /* wait for DRCV to go high */
}
}
void
receive(unsigned char *buffer, unsigned length)
{
register unsigned char data;
/*
* $80 is DRCV (output), $40 is DRDY (input)
*/
ciaa.ciaddrb = 0x80; /* set the bidirectional signals to input */
while (length--) {
while (ciaa.ciaprb & 0x40); /* wait for DRDY to go low */
data = (ciaa.ciaprb & 0x0f) << 4; /* read the high nybble */
ciaa.ciaprb = data & ~0x80; /* set DRCV low */
while (!(ciaa.ciaprb & 0x40)); /* wait for DRDY to go high */
ciaa.ciaprb = data | 0x80; /* set DRCV high */
while (ciaa.ciaprb & 0x40); /* wait for DRDY to go low */
data |= ciaa.ciaprb & 0x0f; /* read the low nybble */
ciaa.ciaprb = data & ~0x80; /* set DRCV low */
while (!(ciaa.ciaprb & 0x40)); /* wait for DRDY to go high */
ciaa.ciaprb = data | 0x80; /* set DRCV high */
*buffer++ = data;
}
}
#endif /* TRANSNIB */